package com.demo.common.config.swagger;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebFlux;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import javax.annotation.PostConstruct;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;


/**
 * @author wuyijie
 * @className: SwaggerAutoConfiguration
 * @description: TODO swagger自动配置类.默认访问地址为 http://127.0.0.1:8010/swagger-ui/index.html
 * @date 2021/4/2 10:43
 */
@Configuration
/**
 * 注入配置类。
 * */
@EnableSwagger2WebMvc
@Import({BeanValidatorPluginsConfiguration.class, WebMvcConfigurerConfig.class})
@EnableConfigurationProperties({SwaggerProperties.class})
/**
 * 根据配置类决定是否进行自动装配
 * */
@ConditionalOnProperty(prefix = "${SwaggerProperties.prefix}", havingValue = "true", name = "${SwaggerProperties.enable}", matchIfMissing = true)
@Slf4j
public class SwaggerAutoConfiguration {

    @Autowired
    private SwaggerProperties swaggerProperties;

    @PostConstruct
    public void init() {
        log.info("SwaggerAutoConfiguration 初始化");
    }



    @Bean(value = "${spring.application.name}-Docket")
    @Order(value = 1)
    public Docket groupRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(groupApiInfo())
                .select()
                .apis(basePackage(swaggerProperties.getBasePackage()))
//                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo groupApiInfo() {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description("<div style='font-size:14px;color:red;'>" + swaggerProperties.getDescription() + "</div>")
                .contact(new Contact(swaggerProperties.getContactUser(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
                .version(swaggerProperties.getVersion())
                .build();
    }


    public static Predicate<RequestHandler> basePackage(final String basePackage) {
        return (input) -> {
            return (Boolean)declaringClass(input).map(handlerPackage(basePackage)).orElse(true);
        };
    }


    private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {
        return input -> {
            // 循环判断匹配
            for (String strPackage : basePackage.split(",")) {
                boolean isMatch = input.getPackage().getName().startsWith(strPackage);
                if (isMatch) {
                    return true;
                }
            }
            return false;
        };
    }

    private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
        return Optional.ofNullable(input.declaringClass());
    }
}
